package org.despair2D.ui.core 
{
	import flash.display.DisplayObject;
	
	import org.despair2D.core.EventDispatcherAdvance;
	import org.despair2D.core.ns_despair;
	import org.despair2D.debug.Logger;
	import org.despair2D.ui.Fusion;
	import org.despair2D.ui.layout.SpaceType;

	use namespace ns_despair;
	
final public class FusionComp extends Component
{
	
	final ns_despair function get headElement() : IComponent { return m_numElement > 0 ? m_elementList[0] : null }
	
	final ns_despair function get tailElement() : IComponent { return m_numElement > 0 ? m_elementList[m_numElement - 1] : null }
	
	
	final ns_despair function addElementAt( c:IComponent, index:int, paddingX:Number, paddingY:Number, spaceCode:int ) : void
	{
		var A:IComponent
		var proxy:ComponentProxy
		var shell:DisplayObject
		
		if (c == this)
		{
			Logger.reportError(this, 'addElementAt', '不可加入自身 !!')
		}
		
		proxy = c as ComponentProxy
		shell = proxy.shell
			
		if(proxy.m_parent)
		{
			Logger.reportError(this, 'addElementAt', '该组件已被加入合体 !!')
		}
		
		proxy.m_parent = this
		
		if (!m_elementList)
		{
			m_elementList = []
		}
		
		if (index == -1)
		{
			this.addChild(shell);
		}
		
		else
		{
			this.addChildAt(shell, index >= 0 ? index : this.numChildren + index + 1);
		}
		
		// horiz layout !!
		switch(spaceCode & 0x000FF)
		{
			case SpaceType.LEFT:
				shell.x = paddingX
				break
				
			case SpaceType.A_LEFT:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.x = A.x + paddingX
				}
				else
				{
					shell.x = paddingX
				}
				break
			
			case SpaceType.A_HORIZ_MIDDLE:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.x = A.x + (A.spaceWidth - proxy.spaceWidth) / 2 + paddingX
				}
				else
				{
					shell.x = paddingX
				}
				break
				
			case SpaceType.A_RIGHT:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.x = A.x + A.spaceWidth + paddingX
				}
				else
				{
					shell.x = this.spaceWidth - proxy.spaceWidth + paddingX
				}
				break
			
			case SpaceType.HORIZ_MIDDLE:
				shell.x = (this.spaceWidth - proxy.spaceWidth) / 2 + paddingX
				break
				
			case SpaceType.RIGHT:
				shell.x = this.spaceWidth - proxy.spaceWidth + paddingX
				break
				
			default:
				Logger.reportError(this, 'addElementAt', 'horiz spaceCode错误(' + (spaceCode & 0x000FF) + ')')
		}
		
		// verti layout !!
		switch(spaceCode & 0x0FF00)
		{
			case SpaceType.TOP:
				shell.y = paddingY
				break
				
			case SpaceType.A_TOP:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.y = A.y + paddingY
				}
				else
				{
					shell.y = paddingY
				}
				break
			
			case SpaceType.A_VERTI_MIDDLE:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.y = A.y + (A.spaceHeight - proxy.spaceHeight) / 2 + paddingY
				}
				else
				{
					shell.y = paddingY
				}
				break
			
			case SpaceType.A_BOTTOM:
				A = (spaceCode & SpaceType.HEAD) ? this.headElement : this.tailElement
				if(A)
				{
					shell.y = A.y + A.spaceHeight + paddingY
				}
				else
				{
					shell.y = this.spaceHeight - proxy.spaceHeight + paddingY
				}
				break
			
			case SpaceType.VERTI_MIDDLE:
				shell.y = (this.spaceHeight - proxy.spaceHeight) / 2 + paddingY
				break
				
			case SpaceType.BOTTOM:
				shell.y = this.spaceHeight - proxy.spaceHeight + paddingY
				break
				
			default:
				Logger.reportError(this, 'addElementAt', 'verti spaceCode错误(' + (spaceCode & 0x0FF00) + ')')
		}
		
		if (m_externalTransform || m_internalTransform)
		{
			Object(proxy).m_view.makeTransform(true, true)
		}
		
		m_elementList[m_numElement++] = c
	}
	
	final ns_despair function removeElement( c:IComponent ) : void
	{
		var index:int
		
		index                 =  m_elementList.indexOf(c);
		m_elementList[index]  =  m_elementList[--m_numElement];
		m_elementList.pop();
	}
	
	final ns_despair function getElementByName( name:String ) : IComponent
	{
		var l:int
		
		l = m_numElement
		while (--l > -1)
		{
			if (m_elementList[l].name == name)
			{
				return m_elementList[l];
			}
		}
		return null;
	}
	
	final ns_despair function getElementAt( index:int ) : IComponent
	{
		return m_elementList[index]
	}
	
	final ns_despair function setElementIndex( c:IComponent, index:int ) : void
	{
		this.setChildIndex(c.displayObject, index)
	}
	
	final ns_despair function removeAllElement() : void
	{
		while (m_numElement > 0)
		{
			m_elementList[--m_numElement].dispose();
		}
		m_elementList = null
	}
	
	final override public function set rotation( v:Number ) : void 
	{
		if (m_rotation != v)
		{
			super.rotation = v;
			if (m_rotation != 0 && !m_internalTransform && !m_externalTransform)
			{
				this.makeTransform(true, false);
			}
			else if (m_rotation == 0 && m_scaleX == 1 && m_scaleY == 1 && !m_externalTransform)
			{
				this.makeTransform(false, false)
			}
		}
	}
	
	final override public function set scaleX( v:Number ) : void 
	{
		if (m_scaleX != v)
		{
			super.scaleX = v;
			if (m_scaleX != 0 && !m_internalTransform && !m_externalTransform)
			{
				this.makeTransform(true, false);
			}
			else if (m_rotation == 0 && m_scaleX == 1 && m_scaleY == 1 && !m_externalTransform)
			{
				this.makeTransform(false, false)
			}
		}
	}
	
	final override public function set scaleY( v:Number ) : void 
	{
		if ( m_scaleY != v)
		{
			super.scaleY = v;
			if (m_scaleY != 0 && !m_internalTransform && !m_externalTransform)
			{
				this.makeTransform(true, false);
			}
			else if (m_rotation == 0 && m_scaleX == 1 && m_scaleY == 1 && !m_externalTransform)
			{
				this.makeTransform(false, false)
			}
		}
	}
	
	ns_despair function makeTransform( smoothing:Boolean, external:Boolean ) : void
	{
		var l:int
		
		if (external)
		{
			m_externalTransform = smoothing
		}
		else
		{
			m_internalTransform = smoothing
		}
		
		if (!m_externalTransform && !m_internalTransform)
		{
			l = m_numElement;
			while (--l > -1)
			{
				m_elementList[l].m_view.makeTransform(false, true);
			}
		}
		else
		{
			l = m_numElement;
			while (--l > -1)
			{
				m_elementList[l].m_view.makeTransform(true, true);
			}
		}
	}
	
	final override ns_despair function dispose() : void
	{
		super.dispose();
		while (m_numElement > 0)
		{
			m_elementList[--m_numElement].dispose();
		}
		m_elementList = null
		m_proxy = null;
		m_eventDispatcher = null
		m_externalTransform = m_internalTransform = false
	}
	
	ns_despair function recycle() : void
	{
		cachedFusionCompList[cachedFusionCompLength++] = this;
	}
	
	ns_despair static function getFusionComp( proxy:Fusion ) : FusionComp
	{
		var FC:FusionComp;
		
		FC = (cachedFusionCompLength > 0 ? cachedFusionCompLength-- : 0) ? cachedFusionCompList.pop() : new FusionComp();
		FC.m_proxy = proxy;
		FC.m_eventDispatcher = new EventDispatcherAdvance(proxy);
		return FC;
	}
	
	
	ns_despair static var cachedFusionCompList:Array = [];
	
	ns_despair static var cachedFusionCompLength:int;
	
	
	ns_despair var m_elementList:Array
	
	ns_despair var m_numElement:int;
	
	ns_despair var m_externalTransform:Boolean, m_internalTransform:Boolean
}
}